package com.springboot.springboot2.config;

import com.springboot.springboot2.bean.Pet;
import com.springboot.springboot2.converter.XxxMessageConverter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.convert.converter.Converter;
import org.springframework.format.FormatterRegistry;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.util.StringUtils;
import org.springframework.web.accept.HeaderContentNegotiationStrategy;
import org.springframework.web.accept.ParameterContentNegotiationStrategy;
import org.springframework.web.filter.HiddenHttpMethodFilter;
import org.springframework.web.servlet.config.annotation.ContentNegotiationConfigurer;
import org.springframework.web.servlet.config.annotation.PathMatchConfigurer;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.util.UrlPathHelper;

import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @ClassName:
 * @author: CKC
 * @DateTime: 2021/1/28 14:39
 */
@Configuration(proxyBeanMethods = true)
public class WebConfig /**implements WebMvcConfigurer*/
{
    @Bean
    public HiddenHttpMethodFilter hiddenHttpMethodFilter() {
        HiddenHttpMethodFilter hiddenHttpMethodFilter = new HiddenHttpMethodFilter();
        
        // hiddenHttpMethodFilter.setMethodParam("_m"); //更改REST风格中的_method
        
        return hiddenHttpMethodFilter;
    }
    
    /**
     * 开启矩阵变量功能有两种方法，方法一：实现接口重写 configurePathMatch
     *
     * @Override public void configurePathMatch(PathMatchConfigurer configurer) {
     * UrlPathHelper urlPathHelper = new UrlPathHelper();
     * // 不移出 分号（；）后面的内容 矩阵变量功能才能生效
     * urlPathHelper.setRemoveSemicolonContent(false);
     * configurer.setUrlPathHelper(urlPathHelper);
     * }
     */
    // 开启矩阵变量功能有两种方法 方法二：
    @Bean
    public WebMvcConfigurer webMvcConfigurer() {
        return new WebMvcConfigurer() {
            /**
             * 开启矩阵变量功能
             * @param configurer
             */
            @Override
            public void configurePathMatch(PathMatchConfigurer configurer) {
                UrlPathHelper urlPathHelper = new UrlPathHelper();
                // 不移出分号（;）后面的内容 矩阵变量功能才能生效
                urlPathHelper.setRemoveSemicolonContent(false);
                configurer.setUrlPathHelper(urlPathHelper);
            }
            //-------------------------------------------------------------------------------------------
            
            /**
             * extendMessageConverters 扩展消息转换器
             *
             * 添加自定义 converter(属性转换器) 协议
             * @param converters
             */
            @Override
            public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
                converters.add(new XxxMessageConverter());
            }
            
            
            /**
             * 自定义内容协商策略
             * @param configurer
             */
            @Override
            public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
                
                Map<String, MediaType> mediaTypeMap = new HashMap<>();
                mediaTypeMap.put("json", MediaType.APPLICATION_JSON);
                mediaTypeMap.put("xml", MediaType.APPLICATION_XML);
                mediaTypeMap.put("xxx", MediaType.parseMediaType("application/xxx"));
                
                //指定支持解析哪些参数对应的哪些媒体类型   基于请求参数的，设置了自定的的内容协商策略(请求参数) ,请求头的默认失效，因此要添加基于请求头的
                ParameterContentNegotiationStrategy parameterStrategy = new ParameterContentNegotiationStrategy(mediaTypeMap);
                //  parameterStrategy.setParameterName("ff"); 设置请求参数的名字  默认是format：format=xml;format=json
                
                //基于请求头的 内容协商
                HeaderContentNegotiationStrategy headerStrategy = new HeaderContentNegotiationStrategy();
                
                configurer.strategies(Arrays.asList(parameterStrategy, headerStrategy));
            }
            //-------------------------------------------------------------------------------------------
            
            /**表单数据 自定义类型转换
             * 以前表单数据填写：
             *     宠物姓名: <input name="pet.name" value="阿猫"/><br/>
             *     宠物年龄: <input name="pet.age" value="5"/><br/>
             * 添加自定义类型转换器后的写法
             *     Pet:<input name="pet" value="啊猫,3" type="text"><br/>
             */
            @Override
            public void addFormatters(FormatterRegistry registry) {
                registry.addConverter(new Converter<String, Pet>() {
                    @Override
                    public Pet convert(String source) {
                        if (!StringUtils.isEmpty(source)) {
                            Pet pet = new Pet();
                            String[] split = source.split(",");
                            pet.setName(split[0]);
                            pet.setWeight(Integer.valueOf(split[1]));
                            return pet;
                        }
                        return null;
                    }
                });
            }
            
            
        };
    }
    
    
}
